一篇小短文,带你了解屏幕刷新背后的故事
屏幕需要在16.7毫秒内绘制完一帧,因为根据研究,16.7ms正符合人类能觉察到卡顿的分割点,如果低于16.7ms,则可能感觉卡顿,高于16.7ms则没必要。
CPU需要在屏幕渲染完毕后,正好把下一帧数据写入帧缓冲。如果早了,那么屏幕上就会绘制一半上一帧的数据,一半下一帧的数据。比如:绘制到第一帧的a行时,cpu把下一帧数据送进来了,屏幕会接着从a+1行接着绘制,这样导致前a行是第一帧的数据,后面几行是第二帧的数据,在我们看来就是两张图片撕开各取一部分拼起来,这叫做「撕裂」。如果晚了,那么屏幕会在下一次继续绘制上一帧,导致画面没有变化,这样就会出现画面不变的情况,在我们看起来就是卡了,也叫做「卡顿」。所以,CPU和屏幕的这个交互时机很重要。
屏幕刷新率(Hz):屏幕在一秒内刷新的次数,Android手机一般都是60Hz,也就是一秒刷新60次,当然也有高刷的,但是60Hz足矣。
帧速率(FPS):cpu在一秒内合成的帧数,比如60FPS,就是60 frame per sconds,意思就是一秒合成60帧。如上所述,当屏幕刷新率大于帧速率的时候,会发生卡顿;屏幕刷新率小于帧速率的时候,会发生撕裂。那么怎么解决这个问题呢,我们一个一个来解决,先来看撕裂。
屏幕正在从前缓冲读取第一帧数据并渲染,此时cpu计算完第二帧数据,放在后缓冲,等待VSYNC信号。
屏幕将第一帧数据渲染完毕,发出VSYNC信号,cpu收到VSYNC信号,将后缓冲的第二帧数据复制到前缓冲。
同时屏幕继续绘制第二帧数据,cpu开始计算下一帧数据,循环往复。
任何一个View都是依附于window的
一个window对应一个surface
view的measure、layout、draw等均是计算数据,这些是cpu干的事
cpu把这些事干好后,在经过一系列计算将数据转交给gpu
gpu将数据栅格化后,就交给SurfeceFlinger(以下简称SF)
SF将多个surfece数据合并处理后,就放入后缓冲区
屏幕以固定频率从前缓冲区拿出数据渲染,渲染完毕后发送VSYNC,此时前后缓冲区数据交换,屏幕绘制下一帧
「cpu -> gpu -> display」,而且我们看到,cpu和gpu是排队工作的,它俩和屏幕是并行工作的。好,我们来看发生卡顿(jank)的场景:
Android 3.0引入了硬件加速(GPU)。
Android 4.0默认开启了硬件加速。
Android 4.1引入了黄油计划(VSYNC),上层开始接收VSYNC(Choreographer),并且加入了三缓冲。
VSYNC不仅控制了后缓冲和前缓冲的数据交换,还控制了cpu何时开始进行绘制计算。